import React, { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
import { Checkbox, Icon, Popconfirm, Switch, Table, Tooltip } from 'antd';
import groupBy from 'lodash/groupBy';
import { array2Tree, filterTreeArrayData, findChildrenItemInTreeArray, findParentItemInTreeArray } from '@/utils/tree';
import { createDictionary } from '@/dictionary';
import useOnceByCondition from '@/hooks/useOnceByCondition';
import styles from './index.module.less';

// 权限功能等级
const [, getFunctionGradeTypeText] = createDictionary('AUTH_FUNCTION_GRADE_TYPE');
// 权限功能类型
const [, getResourceTypeText] = createDictionary('AUTH_RESOURCE_TYPE');

const getCheckedItems = value =>
    value
        .filter(item => {
            const { WEB, APP, PC } = item.selectedScope;
            return !!(WEB || APP || PC);
        })
        .map(item => item.resourceCode);

/**
 * 功能权限选择
 */
const FunctionSelector = React.forwardRef((props, ref) => {
    const { value = [], onChange, disabled, isShow } = props;
    const [isIndependentSetMode, setIsIndependentSetMode] = useState(true); // 独立设置客户端
    const [filteredInfo, setFilteredInfo] = useState(); // 表格过滤信息
    const statisticsData = useMemo(() => {
        // 需要统计的数据(三端只要有一个勾选就需要统计)
        const needCountData = value
            ? value.filter(item => (item?.selectedScope ? Object.values(item.selectedScope).some(val => !!val) : false))
            : [];
        return groupBy(needCountData, 'functionGrade');
    }, [value]);

    // 类型的过滤选项
    const resourceTypeFilters = useMemo(() => {
        if (!value) return [];
        const arr = Array.from(new Set(value.map(item => item.resourceType)));
        return arr.map(item => ({ text: getResourceTypeText(item), value: item }));
    }, [value]);

    // 等级的过滤选项
    const functionGradeFilters = useMemo(() => {
        if (!value) return [];
        const arr = Array.from(new Set(value.map(item => item.functionGrade)));
        return arr.map(item => ({ text: getFunctionGradeTypeText(item), value: item }));
    }, [value]);

    const valueRef = useRef(value);

    useEffect(() => {
        valueRef.current = value;
    }, [value]);

    // 树数据
    const [filterData, filterDataIncludeParents] = useMemo(() => {
        let filterDataIncludeParentsResult = null;
        const filterFn = item => {
            const result = [];
            if (filteredInfo.resourceType?.length) {
                result.push(filteredInfo.resourceType.includes(item.resourceType));
            }
            if (filteredInfo.functionGrade?.length) {
                result.push(filteredInfo.functionGrade.includes(item.functionGrade));
            }
            return !result.some(m => !m);
        };
        let filterDataResult = [];
        // 如果有过滤条件, 就执行过滤
        if (filteredInfo?.resourceType?.length || filteredInfo?.functionGrade?.length) {
            filterDataIncludeParentsResult = filterTreeArrayData(
                valueRef.current,
                filterFn,
                'resourceCode',
                'parentCode'
            );
            filterDataResult = filterDataIncludeParentsResult.filter(filterFn);
            if (valueRef.current.length === filterDataResult.length) {
                filterDataResult = [];
            }
        }
        // 转成树
        return [filterDataResult, filterDataIncludeParentsResult];
    }, [filteredInfo]);

    // 树数据
    const treeData = useMemo(
        () =>
            // 转成树
            array2Tree(filterDataIncludeParents || value, 'resourceCode', 'parentCode'),
        [filterDataIncludeParents, value]
    );

    const [tableExpandedRowKey, setTableExpandedRowKey] = useState([]);

    // 默认展开的行
    useOnceByCondition(() => {
        setTableExpandedRowKey(getCheckedItems(value));
    }, value?.length);

    // 过滤后展开匹配的数据
    useEffect(() => {
        if (filterDataIncludeParents?.length) {
            setTableExpandedRowKey(filterDataIncludeParents.map(item => item.resourceCode));
        } else {
            setTableExpandedRowKey(getCheckedItems(valueRef.current));
        }
    }, [filterDataIncludeParents]);

    // 表格参数变化
    const handleTableExpandRowChange = expandedRows => {
        setTableExpandedRowKey(expandedRows);
    };

    // 表格参数变化
    const handleTableChange = (pagination, filters) => {
        setFilteredInfo(filters);
    };

    // 表格参数变化
    const handleRowClassName = record => {
        if (filterData.some(item => item.resourceCode === record.resourceCode)) {
            return styles.rowHighlight;
        }
        return '';
    };

    // 复选框change事件
    const handleFunctionCheckboxChange = (id, type, checked) => {
        const targetValue = value.find(item => item.resourceCode === id);
        // 查找关联的父节点
        const allParentItem = findParentItemInTreeArray(value, targetValue, 'resourceCode', 'parentCode');
        // 查找关联的子节点
        const allChildrenItem = findChildrenItemInTreeArray(value, targetValue, 'resourceCode', 'parentCode');
        const checkedValue = checked ? 1 : 0;

        // 父节点取消选中, 子节点也要一起取消选中
        const needChangeValues = checked
            ? [targetValue, ...allChildrenItem, ...allParentItem]
            : [targetValue, ...allChildrenItem];
        if (onChange) {
            const result = value.map(item => {
                if (needChangeValues.some(m => m.resourceCode === item.resourceCode)) {
                    const newItem = { ...item };
                    if (isIndependentSetMode) {
                        newItem.selectedScope[type] = newItem.effectiveScope[type] ? checkedValue : null;
                    } else {
                        const { WEB: webEnable, APP: appEnable, PC: pcEnable } = newItem.effectiveScope;
                        newItem.selectedScope = {
                            WEB: webEnable ? checkedValue : 0,
                            APP: appEnable ? checkedValue : 0,
                            PC: pcEnable ? checkedValue : 0
                        };
                    }
                    return newItem;
                }
                return item;
            });
            onChange(result);
        }
    };

    // 独立设置客户端
    const handleIsIndependentSetModeChange = checked => {
        setIsIndependentSetMode(checked);
        if (!checked) {
            // 切换设置方式仅保留三端都开启的功能权限
            if (onChange) {
                const result = value.map(item => {
                    const newItem = { ...item };
                    const { WEB, APP, PC } = newItem.selectedScope;
                    const { WEB: webEnable, APP: appEnable, PC: pcEnable } = newItem.effectiveScope;
                    const checkedValue = (WEB || !webEnable) && (APP || !appEnable) && (PC || !pcEnable) ? 1 : 0;
                    newItem.selectedScope = {
                        WEB: webEnable ? checkedValue : 0,
                        APP: appEnable ? checkedValue : 0,
                        PC: pcEnable ? checkedValue : 0
                    };
                    return newItem;
                });
                onChange(result);
            }
        }
    };

    // 表格列配置
    const columns = [
        {
            title: '功能',
            dataIndex: 'resourceNameZh',
            key: 'resourceNameZh'
        },
        {
            title: '类型',
            dataIndex: 'resourceType',
            key: 'resourceType',
            filters: resourceTypeFilters,
            render: val => getResourceTypeText(val)
        },
        {
            title: '等级',
            dataIndex: 'functionGrade',
            key: 'functionGrade',
            filters: functionGradeFilters,
            render: val => (
                <div style={{ color: ['', '#999', '#555', '#000'][Number(val) || 0] }}>
                    {getFunctionGradeTypeText(val)}
                </div>
            )
        },
        {
            title: () => (
                <div className={styles.newFunctionTableHeader}>
                    <div>功能权限</div>
                    {isIndependentSetMode && (
                        <ul>
                            <li>Web端</li>
                            <li>APP端</li>
                            <li>PC端</li>
                        </ul>
                    )}
                </div>
            ),
            dataIndex: 'selectedScope',
            key: 'selectedScope',
            width: 200,
            align: 'center',
            render: (val = {}, row) => {
                const { WEB, APP, PC } = val;
                const { WEB: webEnable, APP: appEnable, PC: pcEnable } = row.effectiveScope;
                const optionKeys = ['WEB', 'APP', 'PC'];
                const enableMap = [webEnable, appEnable, pcEnable];
                return (
                    <div className={styles.selectedScopeWrapper}>
                        {isIndependentSetMode ? (
                            [WEB, APP, PC].map((item, index) => (
                                <React.Fragment key={optionKeys[index]}>
                                    {!disabled &&
                                        (enableMap[index] === 1 ? (
                                            <Checkbox
                                                checked={item === 1}
                                                onChange={e =>
                                                    handleFunctionCheckboxChange(
                                                        row.resourceCode,
                                                        optionKeys[index],
                                                        e.target.checked
                                                    )
                                                }
                                            />
                                        ) : (
                                            <Tooltip title="功能未上线">
                                                <Checkbox disabled />
                                            </Tooltip>
                                        ))}
                                    {disabled && (item ? <Icon type="check" /> : <Icon type="minus" />)}
                                </React.Fragment>
                            ))
                        ) : (
                            <Checkbox
                                checked={WEB || APP || PC}
                                onChange={() =>
                                    handleFunctionCheckboxChange(row.resourceCode, null, !(WEB || APP || PC))
                                }
                            />
                        )}
                    </div>
                );
            }
        }
    ];

    useImperativeHandle(ref, () => ({
        /**
         * 判断是否有选择的项
         */
        hasCheckedValue: () =>
            value.some(item => {
                const { WEB, APP, PC } = item.selectedScope;
                return !!(WEB || APP || PC);
            }),
        /**
         * 判断是否有选择的项
         */
        getHasCheckedModuleValue: () =>
            value.filter(item => {
                const { WEB, APP, PC } = item.selectedScope;
                return item.resourceType === 1 && !!(WEB || APP || PC); // 取出模块类型且至少有一个端勾选的
            })
    }));

    return (
        !!isShow && (
            <div className={styles.functionList}>
                <div className={styles.topBar}>
                    <div className={styles.statistics}>
                        已选功能：
                        {statisticsData &&
                            Object.keys(statisticsData).map(item => (
                                <span className={styles.statisticsItem} key={item}>
                                    {getFunctionGradeTypeText(item)} {statisticsData[item].length}
                                </span>
                            ))}
                    </div>
                    {!disabled && (
                        <div className={styles.controls}>
                            独立设置客户端
                            {isIndependentSetMode ? (
                                <Popconfirm
                                    placement="topRight"
                                    title={
                                        <>
                                            切换设置方式仅保留三端都开启
                                            <br />
                                            的功能权限，确定关闭吗？
                                        </>
                                    }
                                    onConfirm={() => handleIsIndependentSetModeChange(false)}
                                    okText="确定"
                                    cancelText="取消"
                                >
                                    <Switch checked={isIndependentSetMode} />
                                </Popconfirm>
                            ) : (
                                <Switch checked={isIndependentSetMode} onChange={handleIsIndependentSetModeChange} />
                            )}
                        </div>
                    )}
                </div>
                <Table
                    className={styles.functionListTable}
                    columns={columns}
                    rowKey="resourceCode"
                    pagination={false}
                    dataSource={treeData}
                    expandIcon={({ expanded, onExpand, record }) => {
                        const { children } = record;
                        if (!children || children.length === 0) {
                            return (
                                <span style={{ display: 'inline-block', width: 14, height: 14, marginRight: '5px' }} />
                            );
                        }
                        return expanded ? (
                            <Icon type="caret-down" style={{ marginRight: 5 }} onClick={e => onExpand(record, e)} />
                        ) : (
                            <Icon type="caret-right" style={{ marginRight: 5 }} onClick={e => onExpand(record, e)} />
                        );
                    }}
                    // defaultExpandedRowKeys={defaultExpandedRows}
                    expandedRowKeys={tableExpandedRowKey}
                    onExpandedRowsChange={handleTableExpandRowChange}
                    rowClassName={handleRowClassName}
                    onChange={handleTableChange}
                />
            </div>
        )
    );
});

FunctionSelector.propTypes = {};

FunctionSelector.defaultProps = {};

export default FunctionSelector;
